package smedi.ismedi.web.bff.controller.inmail;

import com.smedi.ismedi.file.dto.response.FileInfoResponse;
import com.smedi.ismedi.file.feign.RemoteFileFeignApi;
import com.smedi.ismedi.inmail.api.dto.request.*;
import com.smedi.ismedi.inmail.api.dto.response.AnnouncementResponse;
import com.smedi.ismedi.inmail.api.dto.response.FileResponse;
import com.smedi.ismedi.inmail.api.dto.response.NodeResponse;
import com.smedi.ismedi.inmail.api.dto.response.ReadRecordResponse;
import com.smedi.ismedi.inmail.api.feign.RemoteAnnouncementFeignApi;
import com.smedi.ismedi.web.starter.common.PaginationData;
import com.smedi.ismedi.web.starter.common.ResponseData;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.tsp.TSPUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import smedi.ismedi.web.bff.infrastructure.util.FileHelper;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;

/**
 * 通知公告BFF
 *
 * @author jiangqinxuan
 * @date 2021/08/03
 */
@Slf4j
@Api(value = "通知公告接口", tags = {"通知公告接口"})
@RequestMapping(value = "/webbff/v1/announcement")
@RestController
@RequiredArgsConstructor
public class AnnouncementController {
    private final RemoteAnnouncementFeignApi remoteAnnouncementFeignApi;

    private final RemoteFileFeignApi fileFeignApi;

    @Value("${fdfs.service.address.in}")
    private String FDFS_SERVICE_ADDRESS_IN;

    /**
     * 新建通知公告
     *
     * @param announcementCreateRequest 通知公告新建请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "新建通知公告")
    @PostMapping(value = "/create")
    ResponseData<AnnouncementResponse> createAnnouncement(@Validated @RequestBody AnnouncementCreateRequest announcementCreateRequest) {
        return remoteAnnouncementFeignApi.createAnnouncement(announcementCreateRequest);
    }

    /**
     * 编辑通知公告
     *
     * @param announcementEditRequest 通知公告编辑请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "编辑通知公告")
    @PostMapping(value = "/edit")
    ResponseData<AnnouncementResponse> editAnnouncement(@Validated @RequestBody AnnouncementEditRequest announcementEditRequest) {
        return remoteAnnouncementFeignApi.editAnnouncement(announcementEditRequest);
    }

    /**
     * 审核通知公告
     *
     * @param announcementReviewRequest 通知公告审核请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "审核通知公告")
    @PostMapping(value = "/review")
    ResponseData<AnnouncementResponse> reviewAnnouncement(@Validated @RequestBody AnnouncementReviewRequest announcementReviewRequest) {
        return remoteAnnouncementFeignApi.reviewAnnouncement(announcementReviewRequest);
    }

    /**
     * 失效通知公告
     *
     * @param announcementDisableRequest 通知公告失效请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "失效通知公告")
    @PostMapping(value = "/disable")
    ResponseData<AnnouncementResponse> disableAnnouncement(@Validated @RequestBody AnnouncementDisableRequest announcementDisableRequest) {
        return remoteAnnouncementFeignApi.disableAnnouncement(announcementDisableRequest);
    }

    /**
     * 删除通知公告
     *
     * @param announcementRemoveRequest 通知公告删除请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "删除通知公告")
    @PostMapping(value = "/remove")
    ResponseData<Boolean> removeAnnouncement(@Validated @RequestBody AnnouncementRemoveRequest announcementRemoveRequest) {
        return remoteAnnouncementFeignApi.removeAnnouncement(announcementRemoveRequest);
    }

    /**
     * 获取 通知公告 单一（详情）
     *
     * @param announcementOneQueryRequest 通知公告单一查询
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "获取 通知公告 单一（详情）")
    @PostMapping(value = "/one")
    ResponseData<AnnouncementResponse> getAnnouncementOne(@Validated @RequestBody AnnouncementOneQueryRequest announcementOneQueryRequest) {
        return remoteAnnouncementFeignApi.getAnnouncementOne(announcementOneQueryRequest);
    }

    /**
     * 获取 组织树
     *
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "GET", value = "获取 组织树")
    @GetMapping(value = "/getOrganizationTree")
    ResponseData<NodeResponse> getOrganizationTree() {
        return remoteAnnouncementFeignApi.getOrganizationTree();
    }

    /**
     * 获取 项目树
     *
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "GET", value = "获取 项目树")
    @GetMapping(value = "/getProjectTree")
    ResponseData<NodeResponse> getProjectTree() {
        return remoteAnnouncementFeignApi.getProjectTree();
    }

    /**
     * 获取 通知公告 列表（通知公告管理）
     *
     * @param announcementPageQueryRequest 通知公告列表查询
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "获取 通知公告 分页（通知公告管理）")
    @PostMapping(value = "/page/management")
    ResponseData<PaginationData<AnnouncementResponse>> getAnnouncementPageInManagement(@Validated @RequestBody AnnouncementPageQueryRequest announcementPageQueryRequest) {
        return remoteAnnouncementFeignApi.getAnnouncementPageInManagement(announcementPageQueryRequest);
    }

    /**
     * 获取 通知公告 列表（个人通知公告）
     *
     * @param announcementPageQueryRequest 通知公告列表查询
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "获取 通知公告 分页（个人通知公告）")
    @PostMapping(value = "/page/person")
    ResponseData<PaginationData<AnnouncementResponse>> getAnnouncementPageInPerson(@Validated @RequestBody AnnouncementPageQueryRequest announcementPageQueryRequest) {
        return remoteAnnouncementFeignApi.getAnnouncementPageInPerson(announcementPageQueryRequest);
    }

    /**
     * 更新 流转单
     *
     * @param announcementReadRecordRequest 流转单 更新 命令
     * @return ResponseEntity<byte [ ]>
     */
    @ApiOperation(httpMethod = "POST", value = "更新 流转单")
    @PostMapping(value = "/read-record/update")
    ResponseData<Boolean> updateReadRecord(@Validated @RequestBody AnnouncementReadRecordRequest announcementReadRecordRequest) throws IOException{
        return remoteAnnouncementFeignApi.updateReadRecord(announcementReadRecordRequest);
    }

    /**
     * 获取 流转单 单一
     *
     * @param readRecordOneQueryRequest 流转单 获取 单一 请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "获取 流转单 单一")
    @PostMapping(value = "/read-record/one")
    ResponseData<String> getReadRecordOne(@Validated @RequestBody ReadRecordOneQueryRequest readRecordOneQueryRequest) throws IOException{
        return remoteAnnouncementFeignApi.getReadRecordOne(readRecordOneQueryRequest);
    }

    /**
     * 获取 流转单 全部（压缩包）
     *
     * @param readRecordAllZipRequest 流转单 获取 单一 请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "获取 流转单 全部（压缩包）")
    @PostMapping(value = "/read-record/all/zip")
    ResponseData<ReadRecordResponse> getAllReadRecordZip(@Validated @RequestBody ReadRecordAllZipRequest readRecordAllZipRequest){
        return remoteAnnouncementFeignApi.getAllReadRecordZip(readRecordAllZipRequest);
    }


    /**
     * 下载 流转单 单一
     *
     * @param readRecordOneQueryRequest 流转单 获取 单一 请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "下载 流转单 单一")
    @PostMapping(value = "/read-record/download")
    void downloadReadRecordOne(@Validated @RequestBody ReadRecordOneQueryRequest readRecordOneQueryRequest) throws IOException{
        ResponseData<String> stringResponseData = remoteAnnouncementFeignApi.downloadReadRecordOne(readRecordOneQueryRequest);
        URL url = new URL(stringResponseData.getData());

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null == requestAttributes) {
            return;
        }
        HttpServletResponse response = requestAttributes.getResponse();
        if (null == response) {
            return;
        }
        response.setContentType("application/x-download");
        response.setHeader("Content-Disposition", "attachment; filename=" + "readRecord.pdf");

        try (InputStream inputStream = url.openStream()) {
            int read = 0;
            byte[] bytes = new byte[1024];
            OutputStream os = response.getOutputStream();

            while ((read = inputStream.read(bytes)) != -1) {
                os.write(bytes, 0, read);
            }
            os.flush();
            os.close();
        }
    }

    /**
     * 导出 通知公告
     *
     * @param announcementExportRequest 通知公告 导出 请求
     * @return ResponseData<AnnouncementResponse>
     */
    @ApiOperation(httpMethod = "POST", value = "导出 通知公告")
    @PostMapping(value = "/announcement/export")
    public ResponseData<Boolean> exportAnnouncement(@Validated @RequestBody AnnouncementExportRequest announcementExportRequest, HttpServletResponse response) {
        String signKey =  remoteAnnouncementFeignApi.exportAnnouncement(announcementExportRequest).getData();
        FileInfoResponse fileInfoResponse = fileFeignApi.getFileInfo(signKey).getData();
        FileHelper.downloadFile(FDFS_SERVICE_ADDRESS_IN, fileInfoResponse.getStorageGroup(), fileInfoResponse.getPath(), fileInfoResponse.getName(), response);

        return new ResponseData<>().success(true);
    }

    @ApiOperation(httpMethod = "POST", value = "指定参数下载附件压缩包")
    @PostMapping(value = "/downloadByParams")
    public ResponseData<FileResponse> postDownloadFilesSetNameToZip(@Validated @RequestBody DownloadFileToZipRequest downloadFileToZipRequest, HttpServletResponse response) throws IOException{
        return remoteAnnouncementFeignApi.postDownloadFilesSetNameToZip(downloadFileToZipRequest);
    }

}
